<?php

namespace common\models\trade;

use Yii;
use yii\base\Exception;

/**
 * This is the model class for table "{{%trade}}".
 */
class HandleTrade extends Trade {

    /**
     * 取消过期交易
     * cancelExpired
     * 
     * @param int $id 交易ID
     * @outputBuffering $msg
     * @return boolean
     */
    public static function cancelExpired($id, &$msg) {
        $trade = static::findOne($id);
        if ($trade == null) {
            $msg = '待操作的交易不存在！';
            return true;
        }
        if ($trade->expire_time > time()) {
            $msg = '当前交易还未过期！';
            return true;
        }
        if ($trade->status !== self::STATUS_DEFAULT && $trade->status !== self::STATUS_WAITPAY) {
            $msg = '当前交易状态已变更，禁止执行过期交易取消操作！';
            return true;
        }
        return static::cancelByTrade($trade, $msg, '交易过期');
    }

    /**
     * 关闭所有当前外部订单号的历史交易
     * Finds order by bizno
     *
     * @param string $bizno
     * @outputBuffering $msg
     * @return boolean
     */
    public static function closeByBizno($bizno, &$msg) {
        $trades = static::find()
        ->where(['bizno' => $bizno])
        ->andWhere([
            'status' => [
                static::STATUS_DEFAULT,
                static::STATUS_WAITPAY
            ]
        ])
        ->all();
        if (empty($trades)) {
            $msg = '未找到您要关闭的交易信息！';
            return false;
        }
        foreach ($trades as $trade) {
            $status = static::cancelByTrade($trade, $msg, '交易关闭');
            if (!$status) {
                return false;
            }
        }
        return true;
    }

    /**
     * 取消所有当前外部订单号的历史交易
     * Finds order by bizno
     *
     * @param string $bizno
     * @outputBuffering $msg
     * @return boolean
     */
    public static function cancelByBizno($bizno, &$msg) {
        $trades = static::find()
        ->where(['bizno' => $bizno])
        ->andWhere([
            'status' => [
                static::STATUS_DEFAULT,
                static::STATUS_WAITPAY
            ]
        ])
        ->all();
        if (empty($trades)) {
            return true;
        }
        foreach ($trades as $trade) {
            $status = static::cancelByTrade($trade, $msg, '待产生新交易');
            if (!$status) {
                return false;
            }
        }
        return true;
    }

    /**
     * 取消交易
     * 
     * @param \common\trade\Trade $trade
     * @outputBuffering $msg
     * @param string|Unkown $prefixMessage
     * @return boolean
     */
    protected static function cancelByTrade($trade, &$msg, $prefixMessage = 'Unkown') {
        $refundOrders = [];
        //未付款或者待支付并且订单已过期则取消当前交易等操作
        $tradeAmount = $trade->getOrders()->sum('pay*balance*status');
        if ($tradeAmount > 0 && !empty($trade->paymentOrder)) {
            //查询当前交易中存在的已支付的交易订单
            foreach ($trade->paymentOrder as $order) {
                $condition = [
                    'trade_id' => $order->trade_id,
                    'original_no' => $order->original_no,
                    'paymode' => $order->paymode,
                    'pay_type' => $order->pay_type,
                    'currency' => $order->currency,
                    'pay' => $order->pay,
                    'balance' => TradeOrder::BALANCE_REFUND,
                ];
                if (TradeOrder::find()->where($condition)->exists()) {
                    continue;
                }
                $refundOrders[$order->paymode] = $condition;
            }
        }
        $transaction = Yii::$app->db->beginTransaction();
        try {
            if (!empty($refundOrders)) {
                foreach ($refundOrders as $paymode => $attributes) {
                    $rollbackOrder = new TradeOrder();
                    $rollbackOrder->attributes = $attributes;
                    $rollbackOrder->setMark('[' . $prefixMessage . ']系统自动取消交易订单');
                    if (!$rollbackOrder->save()) {
                        throw new Exception('退款交易订单申请创建失败！' . print_r($rollbackOrder->errors, true));
                    }
                }
            }
            $recountTradeAmount = $trade->getOrders()->sum('pay*status*balance');
            if ($recountTradeAmount == 0) {
                $trade->setMark('[' . $prefixMessage . ']系统自动关闭当前交易');
                $trade->status = self::STATUS_CLOSED;
            } else {
                $trade->status = self::STATUS_CENCELED;
                $trade->setMark('[' . $prefixMessage . ']系统自动取消当前交易');
            }
            if (!$trade->save()) {
                throw new Exception('交易保存失败！' . print_r($trade->errors, true));
            }
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $msg = $e->getMessage();
            return false;
        }
        return true;
    }

}
